using DA.AnimGraph;
using Unity.Mathematics;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;


namespace DA.AnimGraph.Editor {

    internal class InspectorField_FloatLink : InspectorField<AGAFieldModel_FloatLink> {

        FoldoutPro foldout;
        EnumField linkSourceField;
        FloatField defaultValueField;
        PopupField<AGA_Blackboard.Entry> blackboardField;
        Toggle useClampField;
        FloatField clampRangeMin;
        FloatField clampRangeMax;
        EnumField easeTypeField;
        EnumField functionTypeField;
        Label easeHelper;
        FloatField easeTimeField;


        protected override void BuildUI() {
            foldout = new FoldoutPro() {
                text = $"[float]  {labelText}"
            };

            linkSourceField = new EnumField("source");
            linkSourceField.RegisterValueChangedCallback(evt => OnModify());
            linkSourceField.Init(source.sourceType);

            defaultValueField = new FloatField("value");
            defaultValueField.SetSubFieldLeftPadding();
            defaultValueField.RegisterValueChangedCallback(evt => OnModify());
            defaultValueField.value = source.defaultValue;

            blackboardField = new PopupField<AGA_Blackboard.Entry>("blackboard");
            blackboardField.SetSubFieldLeftPadding();
            blackboardField.RegisterValueChangedCallback(evt => OnModify());

            useClampField = new Toggle("use clamp");
            useClampField.SetSubFieldLeftPadding();
            useClampField.RegisterValueChangedCallback(evt => OnModify());
            useClampField.value = source.useClamp;

            clampRangeMin = new FloatField("min value");
            clampRangeMin.SetSubFieldLeftPadding(2);
            clampRangeMin.RegisterValueChangedCallback(evt => OnModify());
            clampRangeMin.value = source.clampRange.x;

            clampRangeMax = new FloatField("max value");
            clampRangeMax.SetSubFieldLeftPadding(2);
            clampRangeMax.RegisterValueChangedCallback(evt => OnModify());
            clampRangeMax.value = source.clampRange.y;

            easeTypeField = new EnumField("ease type", EaseType.None);
            easeTypeField.SetSubFieldLeftPadding();
            easeTypeField.RegisterValueChangedCallback(evt => OnModify());
            easeTypeField.value = source.easeType;

            functionTypeField = new EnumField("function type", EaseFunctionType.Linear);
            functionTypeField.SetSubFieldLeftPadding(2);
            functionTypeField.RegisterValueChangedCallback(evt => OnModify());
            functionTypeField.value = source.easeFunctionType;

            easeTimeField = new FloatField("ease time");
            easeTimeField.SetSubFieldLeftPadding(2);
            easeTimeField.RegisterValueChangedCallback(evt => OnModify());
            easeTimeField.value = source.easeTime;

            easeHelper = new Label("缓动参考链接") {
                style = {
                    marginLeft = 3,
                    alignSelf = Align.FlexEnd,
                    unityFontStyleAndWeight = FontStyle.Italic,
                    color = AGEStyleUtility.Color(78, 156, 255),
                    cursor = AGEStyleUtility.LoadCursor(MouseCursor.Link), // 鼠标悬停时显示手势
                }
            };
            easeHelper.SetSubFieldLeftPadding(2);
            easeHelper.RegisterCallback<MouseDownEvent>((evt) => {
                if (evt.button == 0) Application.OpenURL("https://easings.net/zh-cn");
            });
        }

        protected override void DrawUI() {
            Add(foldout);
            foldout.Add(linkSourceField);
            switch (source.sourceType) {
                case LinkSourceType.Const:
                    foldout.Add(defaultValueField);
                    break;
                case LinkSourceType.Blackboard:
                    // blackboard
                    var choices = ageContext.GetBlackboardEntriesInType(AGABlackboardType.Float);
                    choices.Insert(0, new AGA_Blackboard.Entry() {
                        name = "(empty)",
                        uuid = default,
                        type = AGABlackboardType.Float,
                    });
                    var selectIndex = choices.FindIndex(p => p.uuid == source.blackboardKey);
                    if (selectIndex < 0) {
                        selectIndex = 0;
                    }
                    blackboardField.choices = choices;
                    blackboardField.index = selectIndex;
                    blackboardField.formatListItemCallback = p => p.name; // 决定每个选项的文本
                    blackboardField.formatSelectedValueCallback = p => p.name; // 决定显示在下拉框中的文本
                    foldout.Add(blackboardField);

                    // ease
                    foldout.Add(easeTypeField);
                    if (source.easeType != EaseType.None) {
                        foldout.Add(functionTypeField);
                        foldout.Add(easeHelper);
                        foldout.Add(easeTimeField);
                    }

                    // clamp
                    foldout.Add(useClampField);
                    if (useClampField.value) {
                        foldout.Add(clampRangeMin);
                        foldout.Add(clampRangeMax);
                    }
                    break;
            }
        }

        protected override void ClearUI() {
            foldout?.Clear();
            Clear();
        }

        private void OnModify() {
            source.sourceType = (LinkSourceType)linkSourceField.value;
            source.defaultValue = defaultValueField.value;
            source.blackboardKey = blackboardField.value.uuid;

            source.useClamp = useClampField.value;
            source.clampRange.x = clampRangeMin.value;
            source.clampRange.y = clampRangeMax.value;

            source.easeType = (EaseType)easeTypeField.value;
            source.easeFunctionType = (EaseFunctionType)functionTypeField.value;
            easeTimeField.value = math.max(easeTimeField.value, 0);
            source.easeTime = easeTimeField.value;

            inspectorChangeCallback?.Invoke();
            ClearUI();
            DrawUI();
        }

    }

}
